package com.iot08.admin.service;

import com.iot08.admin.resp.EntryRecordStatisticsResp;
import com.iot08.admin.service.page.PageVO;
import com.iot08.admin.service.page.PageableImpl;
import com.iot08.common.constant.Const;
import com.iot08.common.entity.admin.SysUser;
import com.iot08.common.entity.app.EntryRecord;
import com.iot08.common.service.base.BaseAdminService;
import com.iot08.common.utils.CollectionUtil;
import com.iot08.common.utils.DateUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

/**
 * @version 1.0
 * @Description:
 * @time: 2020/10/17 9:01
 * @author: Rock
 */
@Service
public class EntryRecordService extends BaseAdminService<EntryRecord> {
//
//    @Resource(name = "appMongoTemplate")
//    private MongoTemplate mongoTemplate;
    @Resource
    private DeviceService deviceService;

    @Resource
    private ImportRecordService importRecordService;

    /**
     * @param agent
     * @param agentUsername
     * @param importNum
     * @param telecom
     * @param importPersonn
     * @time: 2020/10/17 9:10
     * @author: Rock
     * @version 1.0
     */
    public void save(String id, String agent, String agentUsername, Integer importNum, Integer telecom,
                     String importPersonn) {
        EntryRecord er = new EntryRecord();
        er.setId(id);
        er.setAgent(agent);
        er.setAgentUsername(agentUsername);
        er.setImportNum(importNum);
        if (telecom == null) {
            er.setTelecom(0);
        } else {
            er.setTelecom(telecom);
        }
        er.setImportPersonn(importPersonn);
        er.setImportTime(new Date());
        er.setActiveNum(0);
        er.setBindNum(0);
        mongoTemplate.save(er);
    }

    /**
     * @param page
     * @param agentUsername
     * @param telecom
     * @param startTime
     * @param endTime
     * @time: 2020/10/21 9:00
     * @author: Rock
     * @version 1.0
     */
    public Page<EntryRecord> list(PageVO page, String agentUsername, Integer telecom, String startTime,
                                  String endTime, SysUser user) {
        PageableImpl pageable = new PageableImpl();
        page.setSort(Sort.by(Sort.Order.desc("ImportTime")));
        pageable.setPage(page);

        Criteria criteria = new Criteria();
        if (StringUtils.isNotEmpty(page.getSearchValue())) {
            criteria.and("id").regex(".*?" + page.getSearchValue() + ".*?", "i");
        }
        if (StringUtils.isNotEmpty(agentUsername)) {
            criteria.and("agent_username").regex(".*?" + agentUsername + ".*?", "i");
        }
        if (telecom != null) {
            criteria.and("telecom").is(telecom);
        }
        if (StringUtils.isNotEmpty(startTime) && StringUtils.isNotEmpty(endTime)) {
            criteria.and("ImportTime").gte(DateUtil.strToDate(startTime)).lte(DateUtil.strToDate(endTime));
        } else if (StringUtils.isNotEmpty(startTime)) {
            criteria.and("ImportTime").gt(DateUtil.strToDate(startTime));
        } else if (StringUtils.isNotEmpty(endTime)) {
            criteria.and("ImportTime").lt(DateUtil.strToDate(endTime));
        }
        if (user.getType() == Const.CHANNELUSER_TYPE) {
            criteria.orOperator(Criteria.where("agent").in(CollectionUtil.longToStr(user.getChannelAff().getChannelCodes())),
                    Criteria.where("agent").exists(false));
        }

        Query query = new Query().addCriteria(criteria);
        long count = mongoTemplate.count(query, EntryRecord.class);
        page.setTotalResult((int) count);
        List<EntryRecord> list = mongoTemplate.find(query.with(pageable), EntryRecord.class);

        List<EntryRecord> changeOldEntryRecordList = importRecordService.doChangeImportRecordList();
        if(!changeOldEntryRecordList.isEmpty()){
            list.addAll(changeOldEntryRecordList);
            count += changeOldEntryRecordList.size();
        }
        list.forEach(e->{
            if(ObjectUtils.isNotEmpty(e.getBindNum()) && ObjectUtils.isNotEmpty(e.getImportNum()) && !Integer.valueOf(0).equals(e.getImportNum())) {
                e.setBindRadio(new BigDecimal(e.getBindNum()).divide(new BigDecimal(e.getImportNum()), 3, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal(100)).setScale(2,RoundingMode.HALF_UP).toString());
            } else {
                e.setBindRadio("0.00");
            }
        });
        Page<EntryRecord> result = new PageImpl<EntryRecord>(list, pageable, count);
        return result;
    }


    /**
     * @description 查询统计数据
     * @author cwj
     * @param [id, agentUsername, telecom, startTime, endTime, user]
     * @return com.iot08.admin.resp.EntryRecordStatisticsResp
     * @date @time 2025/4/30 12:02
     **/
    public EntryRecordStatisticsResp queryStatisticsData(String id,String agentUsername, Integer telecom, String startTime, String endTime,SysUser user){
        EntryRecordStatisticsResp ersr = new EntryRecordStatisticsResp();
        Criteria criteria = new Criteria();
        if (StringUtils.isNotEmpty(id)) {
            criteria.and("_id").regex(".*?" + id + ".*?", "i");
        }
        if (StringUtils.isNotEmpty(agentUsername)) {
            criteria.and("agent_username").regex(".*?" + agentUsername + ".*?", "i");
        }
        if (telecom != null) {
            criteria.and("telecom").is(telecom);
        }
        if (StringUtils.isNotEmpty(startTime) && StringUtils.isNotEmpty(endTime)) {
            criteria.and("ImportTime").gte(DateUtil.strToDate(startTime)).lte(DateUtil.strToDate(endTime));
        } else if (StringUtils.isNotEmpty(startTime)) {
            criteria.and("ImportTime").gt(DateUtil.strToDate(startTime));
        } else if (StringUtils.isNotEmpty(endTime)) {
            criteria.and("ImportTime").lt(DateUtil.strToDate(endTime));
        }
        if (user.getType() == Const.CHANNELUSER_TYPE) {
            criteria.orOperator(Criteria.where("agent").in(CollectionUtil.longToStr(user.getChannelAff().getChannelCodes())),
                    Criteria.where("agent").exists(false));
        }
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group()
                        .sum("import_num").as("importTotal")
                        .sum("active_num").as("activeTotal")
                        .sum("bind_num").as("bindTotal")
        );
        AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, "entry_record", Document.class);
        Document result = results.getUniqueMappedResult();
        if(ObjectUtils.isNotEmpty(result)) {
            ersr.setImportTotal(ObjectUtils.isNotEmpty(result.get("importTotal"))?result.getLong("importTotal"):0);
            ersr.setActiveTotal(ObjectUtils.isNotEmpty(result.get("activeTotal"))?result.getLong("activeTotal"):0);
            ersr.setBindTotal(ObjectUtils.isNotEmpty(result.get("bindTotal"))?result.getLong("bindTotal"):0);
            if(!Long.valueOf(0).equals(ersr.getImportTotal())){
                ersr.setActiveTotalRadio(new BigDecimal(ersr.getActiveTotal()).divide(new BigDecimal(ersr.getImportTotal()), 3, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal(100)).setScale(2,RoundingMode.HALF_UP).toString());
                ersr.setBindTotalRadio(new BigDecimal(ersr.getBindTotal()).divide(new BigDecimal(ersr.getImportTotal()), 3, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal(100)).setScale(2,RoundingMode.HALF_UP).toString());
                ersr.setBindActiveTotalRadio(new BigDecimal(ersr.getBindTotal()).divide(new BigDecimal(ersr.getActiveTotal()), 3, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal(100)).setScale(2,RoundingMode.HALF_UP).toString());
            } else {
                ersr.setActiveTotalRadio("0.00");
                ersr.setBindTotalRadio("0.00");
            }
        }
        return ersr;
    }


    /**
     * @time: 2020/10/31 10:52
     * @author: Rock
     * @version 1.0
     */
    public void updateNumJop() {
        List<String> ids = mongoTemplate.findDistinct("_id", EntryRecord.class, String.class);
        for (String id : ids) {
            if (StringUtils.isEmpty(id)) {
                continue;
            }
            long importNum = deviceService.countByProductionBatch(id);
            if (importNum > 0) {
                long activeNum = deviceService.countActiveNumByProductionBatch(id);
                long bindNum = deviceService.countBindNumByProductionBatch(id);
                BigDecimal activeRadio = new BigDecimal(activeNum * 100).divide(new BigDecimal(importNum), 2, BigDecimal.ROUND_HALF_UP);
                Update update = new Update().set("import_num", importNum).set("active_num", activeNum).set("bind_num", bindNum);
                update.set("active_radio", activeRadio.toString());
                mongoTemplate.updateFirst(new Query(Criteria.where("_id").is(id)), update, EntryRecord.class);
            } else {
                mongoTemplate.remove(new Query(Criteria.where("_id").is(id)), EntryRecord.class);
            }
        }
    }

}
